home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue36 / frmcache / FormCaching.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1998-05-29  |  5.6 KB  |  212 lines

  1. unit FormCaching;
  2.  
  3. // Provides a FormCache object to handle form caching
  4. // Written by Philip Brown of Informatica Consultancy & Development
  5. // phil@informatica.uk.com
  6.  
  7. interface
  8.  
  9. uses
  10.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms;
  11.  
  12. type
  13.   TFormCacheItem = record
  14.     DateTimeLastUsed: TDateTime;
  15.     Form: TForm;
  16.     IsInUse: Boolean;
  17.   end;
  18.   PFormCacheItem = ^TFormCacheItem;
  19.  
  20.   TFormCache = class
  21.   private
  22.     FormList: TList;
  23.     FMaximumCacheSize: Integer;
  24.     function GetForms (Index: Integer): PFormCacheItem;
  25.     constructor Create;
  26.     destructor Destroy; override;
  27.     function GetCount: Integer;
  28.     function GetActiveCount: Integer;
  29.     procedure SetMaximumCacheSize (Value: Integer);
  30.   protected
  31.     property Forms[Index: Integer]: PFormCacheItem read GetForms; default;
  32.   public
  33.     function CreateForm (FormClassToCreate: TFormClass): TForm;
  34.     procedure FreeForm (FormToFree: TForm);
  35.     property MaximumCacheSize: Integer read FMaximumCacheSize write SetMaximumCacheSize;
  36.     property Count: Integer read GetCount;
  37.     property ActiveCount: Integer read GetActiveCount;
  38.   end;
  39.  
  40. var
  41.   FormCache: TFormCache;
  42.  
  43. implementation
  44.  
  45. // TFormCache
  46.  
  47. constructor TFormCache.Create;
  48. begin
  49.   inherited;
  50.   FormList := TList.Create;
  51.   FMaximumCacheSize := 10;
  52. end;
  53.  
  54. destructor TFormCache.Destroy;
  55. var
  56.   ThisForm: Integer;
  57. begin
  58.   for ThisForm := 0 to Count - 1 do begin
  59.     Forms[ThisForm]^.Form.Free;
  60.     Dispose (FormList[ThisForm]);
  61.   end;
  62.   FormList.Free;
  63.   inherited;
  64. end;
  65.  
  66. function TFormCache.GetCount: Integer;
  67. begin
  68.   Result := FormList.Count;
  69. end;
  70.  
  71. function TFormCache.GetActiveCount: Integer;
  72. var
  73.   ThisForm: Integer;
  74. begin
  75.   Result := 0;
  76.   for ThisForm := 0 to Count - 1 do begin
  77.     if Forms[ThisForm]^.IsInUse then begin
  78.       Inc (Result);
  79.     end;
  80.   end;
  81. end;
  82.  
  83. procedure TFormCache.SetMaximumCacheSize (Value: Integer);
  84. var
  85.   ThisForm: Integer;
  86. begin
  87.   FMaximumCacheSize := Value;
  88.   ThisForm := 0;
  89.   while (ThisForm < Count) and (Count > MaximumCacheSize) do begin
  90.     with Forms[ThisForm]^ do begin
  91.       if IsInUse then begin
  92.         Inc (ThisForm);
  93.       end else begin
  94.         // cache can be reduced
  95.         Form.Free;
  96.         Dispose (FormList[ThisForm]);
  97.         FormList.Delete (ThisForm);
  98.       end;
  99.     end;
  100.   end;
  101. end;
  102.  
  103. function TFormCache.GetForms (Index: Integer): PFormCacheItem;
  104. begin
  105.   Result := PFormCacheItem (FormList[Index]);
  106. end;
  107.  
  108. function TFormCache.CreateForm (FormClassToCreate: TFormClass): TForm;
  109. var
  110.   FormCacheItemPtr: PFormCacheItem;
  111.   ThisIndex: Integer;
  112.   OldestDate: TDateTime;
  113.   OldestFormIndex: Integer;
  114. begin
  115.   Result := nil;
  116.   OldestDate := Now;
  117.   OldestFormIndex := -1;
  118.   ThisIndex := 0;
  119.   while (Result = nil) and (ThisIndex < Count) do begin
  120.     // test for class match
  121.     with Forms[ThisIndex]^ do begin
  122.       if not IsInUse then begin
  123.         if (Form <> nil) and (Form.ClassType = FormClassToCreate) then begin
  124.           Result := Form;
  125.           IsInUse := True;
  126.           // call the form OnCreate event if it is Assigned
  127.           if Assigned (Result.OnCreate) then begin
  128.             Result.OnCreate (Result);
  129.           end;
  130.         end else if DateTimeLastUsed < OldestDate then begin
  131.           // remember the oldest "slot" available for a new form
  132.           OldestFormIndex := ThisIndex;
  133.           OldestDate := DateTimeLastUsed;
  134.         end;
  135.       end;
  136.     end;
  137.     Inc (ThisIndex);
  138.   end;
  139.   // if Result is nil then we have failed to find a useable, cached entry so
  140.   // we must create one
  141.   if Result = nil then begin
  142.     // no cached entry exists, we must create a new instance using standard methods
  143.     Result := FormClassToCreate.Create (nil);
  144.     // check to see if our cache can accept this new form
  145.     if Count = MaximumCacheSize then begin
  146.       // not allowed to add another cached form to the list, see if we had a reusable slot in the cache
  147.       if OldestFormIndex <> -1 then begin
  148.         // reuse the oldest cache entry
  149.         with Forms[OldestFormIndex]^ do begin
  150.           // free up the old form
  151.           Form.Free;
  152.           // assign our new one to the cache
  153.           Form := Result;
  154.           IsInUse := True;
  155.         end;
  156.       end;
  157.     end else begin
  158.       // add this form to the cache
  159.       New (FormCacheItemPtr);
  160.       FormCacheItemPtr^.DateTimeLastUsed := 0;
  161.       FormCacheItemPtr^.Form := Result;
  162.       FormCacheItemPtr^.IsInUse := True;
  163.       FormList.Add (FormCacheItemPtr);
  164.     end;
  165.   end;
  166. end;
  167.  
  168. procedure TFormCache.FreeForm (FormToFree: TForm);
  169. var
  170.   FoundForm: Boolean;
  171.   ThisIndex: Integer;
  172. begin
  173.   // try and find the form in the cache
  174.   ThisIndex := 0;
  175.   FoundForm := False;
  176.   while (not FoundForm) and (ThisIndex < Count) do begin
  177.     with Forms[ThisIndex]^ do begin
  178.       if Form = FormToFree then begin
  179.         // found instance, free it up
  180.         FoundForm := True;
  181.         if Count > MaximumCacheSize then begin
  182.           // shrink the cache - remove the cache entry
  183.           Form.Free;
  184.           Dispose (FormList[ThisIndex]);
  185.           FormList.Delete (ThisIndex);
  186.         end else begin
  187.           // flag cache entry as available and timestamp it
  188.           IsInUse := False;
  189.           DateTimeLastUsed := Now;
  190.         end;
  191.       end else begin
  192.         Inc (ThisIndex);
  193.       end;
  194.     end;
  195.   end;
  196.   // if we could not find the form in the cache then we should just free it -
  197.   // it was not in the cache in the first place
  198.   if not FoundForm then begin
  199.     FormToFree.Free;
  200.   end
  201. end;
  202.  
  203. // unit routines
  204.  
  205. initialization
  206.   FormCache := TFormCache.Create;
  207.  
  208. finalization
  209.   FormCache.Free;
  210.  
  211. end.
  212.